// part1:C12:ex12.28.cpp
// search text.
#include <iostream>
#include <fstream>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <set>
// #include <cstring>
#include <cstdlib>
#include "make_plural.h"
using namespace std;
using line_no = vector<string>::size_type;

vector<string> file;
map<string, set<line_no>> wm;

string cleanup_str(const string &word)
{
  string ret;
  for (auto it = word.begin(); it != word.end(); ++it)
  {
    if (!ispunct(*it))
    {
      ret += tolower(*it);  
    }
  }
  return ret;
}

void input_text(ifstream &is)
{
  string text;
  while (getline(is, text))
  {
    file.push_back(text);
    int n = file.size() - 1;
    istringstream line(text);
    string word;
    while (line >> word)
    {
      // insert line_no to set 
      // if word not in wm, word as a new item of wm.
      wm[cleanup_str(word)].insert(n);
      
    }
  }
}

ostream &query_and_print(const string &sought, ostream &os)
{
  // use find to search word.
  // do not add word to wm.
  auto loc = wm.find(sought);
  if (loc == wm.end())
  {
    os << sought << " has 0" << endl;
  } 
  else 
  {
    auto lines = loc ->second;
    os << sought << "has " << lines.size() << endl;
    for (auto num : lines)
    {
      os << "\t[" << num + 1 << "]line: "
         << *(file.begin() + num) << endl;
    }
  }
  return os;
}

void runQuerlies(ifstream &infile)
{ // infile as ifstream, point to file, which would be searched.
  input_text(infile);
  // input word to search.
  while (true) 
  {
    cout << "enter word to look for, or q to quit: ";
    string s1;
    if (!(cin >> s1) || s1 == "q")
    {
      break;
    }

    query_and_print(s1, cout) << endl;
  }
}

// accept an argument, as name of text file.
int main(int argc, char **argv)
{
  ifstream infile;
  if (argc < 2 || !(infile.open(argv[1]), infile))
  {
    cerr << "No input file!" << endl;
    return EXIT_FAILURE;
  }

  runQuerlies(infile);
  return 0;
}